package switchviz.core.mib;

import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import switchviz.core.ResourceManager;
import switchviz.core.SwitchVizException;
import switchviz.gui.component.XMLTree;
import switchviz.gui.component.XMLTreeNode;
import switchviz.util.StringUtil;


public class MIBTree extends XMLTree
{
	private static final long serialVersionUID = 2353838954945277468L;
	
	public static final String MIBNODEDESCRIPTION = "description";
	public static final String MIBNODETYPE = "type";
	public static final String MIBNODERANGE = "range";
	public static final String MIBNODEPORT = "portrequired";
	public static final String MIBNODERANGEFROM = "from";
	public static final String MIBNODERANGETO = "to";
	public static final String MIBNODENAME = "name";
	public static final String MIBNODEOID = "id";
	public static final String MIBNODE = "node";
	
	public MIBTree(File xmlfile) throws JDOMException, IOException 
	{
		super(xmlfile);
		this.setPreferredSize(new Dimension(400, 400));
	    this.setLeafNodeIcon(ResourceManager.getInstance().getImageIconMIBNode());
	}

	public void addMIBNode(String nodetext, String name, String oid)
	{
		Element newEl = new Element(MIBNODE);
		newEl.setAttribute(MIBNODENAME, name);
		newEl.setAttribute(MIBNODEOID, oid);
		addNode(new XMLTreeNode(nodetext, newEl));
	}
	
	public void changeCurrentNode(MIBDataModel datamodel)
	{
		Element aspectElement;
		XMLTreeNode actNode = (XMLTreeNode)_jtree.getLastSelectedPathComponent();	
		actNode.getElement().setAttribute(MIBNODENAME, datamodel.getName());
		actNode.getElement().setAttribute(MIBNODEOID, datamodel.getOID());
		actNode.setUserObject(datamodel.getName() + " :: " + datamodel.getOID());
		
		aspectElement = actNode.getElement().getChild(MIBNODEDESCRIPTION);
		if (aspectElement == null)
			actNode.getElement().addContent(new Element(MIBNODEDESCRIPTION).setText(datamodel.getDescription()));
		else
			aspectElement.setText(datamodel.getDescription());
		
		aspectElement = actNode.getElement().getChild(MIBNODETYPE);
		if (aspectElement == null)
			actNode.getElement().addContent(new Element(MIBNODETYPE).setText(datamodel.getType()));
		else
			aspectElement.setText(datamodel.getType());
		
		aspectElement = actNode.getElement().getChild(MIBNODERANGE);
		if (aspectElement == null)
		{
			aspectElement = new Element(MIBNODERANGE);
			aspectElement.setAttribute(MIBNODERANGEFROM , String.valueOf(datamodel.getRangeLow()));
			aspectElement.setAttribute(MIBNODERANGETO , String.valueOf(datamodel.getRangeHigh()));
			actNode.getElement().addContent(aspectElement);
		}
		else
		{
			aspectElement.setAttribute(MIBNODERANGEFROM, String.valueOf(datamodel.getRangeLow()));
			aspectElement.setAttribute(MIBNODERANGETO, String.valueOf(datamodel.getRangeHigh()));
		}
		
		aspectElement = actNode.getElement().getChild(MIBNODEPORT);
		if (aspectElement == null)
			actNode.getElement().addContent(new Element(MIBNODEPORT).setText(String.valueOf(datamodel.getPortRequired())));
		else
			aspectElement.setText(String.valueOf(datamodel.getPortRequired()));
		
		_treemodel.reload(actNode);
	}
	
	@SuppressWarnings(value={"unchecked"}) 
	public static MIBDataModel getDataModel(String oid) throws SwitchVizException
	{
		try
		{
			Document doc = new SAXBuilder().build(ResourceManager.getInstance().getMIBConfigurationFile());
			Element element = doc.getRootElement();
				
			String[] path = StringUtil.tokenize(oid, ".");
			
			int currentPosition = 0;
			while (currentPosition < path.length)
			{
				boolean found = false;
				List<Element> childrens = element.getChildren(MIBNODE);

				for (int i = 0; i < childrens.size() && !found; ++i)
				{
					String[] nodeId = StringUtil.tokenize(childrens.get(i).getAttribute(MIBNODEOID).getValue(), "."); 
					
					boolean match = true;
					for (int j = 0; j < nodeId.length && match; ++j)
						match = nodeId[j].equals(path[currentPosition + j]);
					
					if (match)
					{
						found = true;
						
						currentPosition += nodeId.length;
						element = childrens.get(i);
					}
				}
				
				if (found == false)
					return null;
			}
			
			return elementToModel(element);
		} catch (Exception e)
		{
			throw new SwitchVizException("Error parsing mib for '" + oid + "'.", e);
		}
	}
	
	private static MIBDataModel elementToModel(Element element) throws SwitchVizException
	{			
		try
		{
			long rangeFrom = 0, rangeTo = 0;	
			boolean portRequired = false;

			if (element.getChild(MIBNODERANGE) != null)
			{
				if (element.getChild(MIBNODERANGE).getAttribute(MIBNODERANGEFROM) != null 
						&& element.getChild(MIBNODERANGE).getAttribute(MIBNODERANGEFROM).getValue().length() != 0)
					rangeFrom = Long.parseLong(element.getChild(MIBNODERANGE).getAttribute(MIBNODERANGEFROM).getValue());
				
				if (element.getChild(MIBNODERANGE).getAttribute(MIBNODERANGETO) != null 
						&& element.getChild(MIBNODERANGE).getAttribute(MIBNODERANGETO).getValue().length() != 0)
					rangeTo = Long.parseLong(element.getChild(MIBNODERANGE).getAttribute(MIBNODERANGETO).getValue());
			}
	
			if (element.getChildText(MIBNODEPORT) != null 
					&& element.getChildText(MIBNODEPORT).length() != 0)
				portRequired = Boolean.parseBoolean(element.getChildText(MIBNODEPORT));

			return new MIBDataModel(element.getAttributeValue(MIBNODENAME), 
					element.getAttributeValue(MIBNODEOID), 
					element.getChildText(MIBNODEDESCRIPTION) != null ? element.getChildText(MIBNODEDESCRIPTION) : "", 
					element.getChildText(MIBNODETYPE) != null ? element.getChildText(MIBNODETYPE) : "", 
					rangeFrom,
					rangeTo, 
					portRequired);
				
		}catch (Exception e)
		{
			throw new SwitchVizException("Error parsing oid data model.", e);
		}
	}
	
	public static void main(String[] args) throws Exception
	{
		MIBDataModel dataModel = MIBTree.getDataModel("1.3.6.1.2.1.1.1.0");
		
		System.out.println(dataModel.getName());
	}
}
